import EventTarget from './EventTarget'
import PointIn from './PointIn'
interface BezierAttr {
	duration?: number
	delay?: number
	name?: string|number[]
	count?: number
	zoom?: number
	forward?: boolean
	autoplay?: boolean
}
export default class Bezier extends EventTarget{
	_delay:number = 0;
	_time:number = 0;
	_forward:number|boolean = 0;
	duration:number = 800;
	delay:number = 0;
	name:string|number[] = 'ease';
	count:number = 1;
	zoom:number = 100;
	forward:boolean = false;
	points:number[];
	curcount:number;
	autoplay:boolean = true;
	framerate:number;
	rate:number;
	state:string;
	static _: Bezier[] = []
	constructor(options?:BezierAttr){
		super()
		Object.assign(this, options);
		let writableNum = {
			writable: true,
			configurable: false,
			enumerable: false,
			value: 0
		}
		Object.defineProperties(this, {
			curcount: writableNum,
			framerate: {
				writable: true,
				configurable: false,
				enumerable: false,
				value: 60
			},
			rate: writableNum,
			state: {
				writable: true,
				configurable: false,
				enumerable: false,
				value: this.autoplay ? 'play' : 'stop'
			},
			points: {
				writable: true,
				configurable: false,
				enumerable: false,
				value: []
			},
			_time: writableNum,
			_delay: writableNum,
			_forward: writableNum
		});
		this.compute();
		this.emit('ready')
	}
	compute(){
		let points:number[] = [];
		if(typeof this.name === 'string'){
			points.push(0, 0);
			switch(this.name){
				case 'ease':
					points.push(.25, .1, .25, 1);
					break;
				case 'ease-in':
					points.push(.42, 0);
					break;
				case 'ease-out':
					points.push(.58, 1);
					break;
				case 'ease-in-out':
					points.push(.42, 0, .58, 1);
					break;
			}
			points.push(1, 1);
			points.forEach((item, index)=> {
				points[index] = item * this.zoom;
			});
		}else{
			let i=0,len=this.name.length;
			if(len%2) len--;
			for(; i<len; i++){
				points[i] = this.name[i] * this.zoom;
			}
		}
		this.points = points;
	}
	ticker(delta:number){
		if(this.state === 'play'){
			if(this._delay <= 0 && (this.count === 0 || this.curcount < this.count)){
				this.emit('beforeUpdate')
				let arr = PointIn.bezierPoint(this.points, this._time / this.duration, this.process);
				if(!arr) return;
				if(this._time < this.duration) {
					this.rate = this._forward ?  (1 - arr[1] / this.zoom) : (arr[1] / this.zoom);
					this.emit('update', arr)
				}else{
					this.rate = this._forward ? 0 : 1;
					this.emit('update', [this.zoom, this.zoom])
					this.curcount++;
					if(this.count === 0 || this.curcount < this.count){
						this.emit('borderNext')
					}else{
						this.stop();
						this.emit('ended')
					}
					this._time = 0;
					this._forward = (this.forward && this.curcount%2 !== 0);
				}
				this._time += delta;
			}else{
				this._delay -= delta;
			}
		}
	}
	process(arr:number[]){}
	start(){
		this.state = 'play';
	}
	stop(){
		this.curcount = 0;
		this.rate = 0;
		this._delay = this.delay;
		this.state = 'stop';
		this._time = 0;
		this._forward = 0;
	}
	pause(){
		this.state = 'pause';
	}
	destroy(){
		let arr = Bezier._
		let len = arr.length
		let i = 0
		for(; i<len; i++){
			if(arr[i] === this) {
				arr.splice(i, 1);
				break;
			}
		}
	}
}
